package com.fashion.web.filter;

import com.fashion.utils.StringUtils;
import com.fashion.utils.URLMapping;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import org.apache.log4j.Logger;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User: Administrator Date: 11-10-10 Time: 上午10:23
 */
public class UrlFilter implements Filter {
    List<URLMapping> urlPatternList;
    private static final Logger logger = Logger.getLogger(UrlFilter.class);

    /**
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        /**
         * 初始化
         */
        String configPath = fConfig.getInitParameter("configPath");
        String realConfigPath = fConfig.getServletContext().getRealPath(
                configPath);
        FileInputStream input;
        byte buff[] = null;
        try {
            input = new FileInputStream(realConfigPath);
            buff = new byte[input.available()];
            input.read(buff);
            input.close();
        } catch (Exception e) {
            logger.error("Error in read configuration for UrlFilter!", e);
        }

        /**
         * 通过开源XStream来解析XML，并转化成Java对象
         */
        XStream xstream = new XStream(new DomDriver());
        xstream.alias("url", URLMapping.class);
        xstream.alias("URLList", ArrayList.class);
        urlPatternList = (List) xstream.fromXML(new String(buff));

        // Get spring context and then get column service
        /*
           * ServletContext servletContext = fConfig.getServletContext();
           * ApplicationContext context =
           * WebApplicationContextUtils.getWebApplicationContext(servletContext);
           * ColumnService columnService = (ColumnService)
           * context.getBean("columnService"); columns =
           */
    }

    /**
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
    }

    /**
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
     *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        /**
         * 获得服务器名称，如：firefly.iteye.com/
         */
        String serverName = request.getServerName();

        int endIndex = serverName.indexOf(".");
        /**
         * 获得二级域名 二级域名一般是一个ID, 如：pic
         */
        String secondDomainName = serverName;
        String requestURI = httpServletRequest.getRequestURI();
        String requestURL = httpServletRequest.getRequestURL().toString();
        // hack for bbs
        if (requestURI.contains("/bbs")) {
            httpServletRequest.getRequestDispatcher("/bbs/index.html").forward(
                    request, response);

            return;
        }

        if (endIndex > 0) {
            secondDomainName = serverName.substring(0, endIndex);
        }

        String realPath = findRealPath(secondDomainName, requestURI);
        logger.debug("request info: " + requestURL);
        logger.debug("request realPath: " + realPath);
        request.setAttribute("originalURL", requestURL);
        request.setAttribute("mappedURL", realPath);
        if (requestURI.contains("/tag/") || requestURI.contains("/ciku/")) {
            request.setAttribute("encodedTagName", StringUtils.captureAfter(realPath, "tag="));
        }

        if (realPath.equalsIgnoreCase("/")) {
            if (isDomainName(secondDomainName)) {
                httpServletRequest.getRequestDispatcher("/index.action")
                        .forward(request, response);
            } else {
                httpServletRequest.getRequestDispatcher(
                        forwardToSecondDomain(secondDomainName)).forward(
                        request, response);
            }

        } else {
            logger.debug("request info: " + requestURI + " " + realPath);
            httpServletRequest.getRequestDispatcher("/" + realPath).forward(
                    request, response);
        }
    }

    protected String forwardToSecondDomain(String secondDomainName) {
        if ("news".equalsIgnoreCase(secondDomainName)) {
            return "/news/index.action";
        } else if ("pic".equalsIgnoreCase(secondDomainName)) {
            return "/gallery/index.action";
        } else if ("luxury".equalsIgnoreCase(secondDomainName)) {
            return "/luxury/index.action";
        } else if ("fashion".equalsIgnoreCase(secondDomainName)) {
            return "/fashion/index.action";
        } else if ("life".equalsIgnoreCase(secondDomainName)) {
            return "/life/index.action";
        } else if ("brand".equalsIgnoreCase(secondDomainName)) {
            return "/brand/index.action";
        } else if ("people".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=people&columnUrl=people";
        } else if ("activity".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=activity&columnUrl=activity";
        } else if ("video".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=video&columnUrl=video";
        } else if ("special".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=special&columnUrl=special";
        } else if ("top".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=top&columnUrl=top";
        }
        //hack for old fengsung columns
        else if ("digital".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=life&columnUrl=shangpin";
        } else if ("golf".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=life&columnUrl=gaoerfu";
        } else if ("xcar".equalsIgnoreCase(secondDomainName)) {
            return "/management/news/searchColumnNews.action?topColumnUrl=luxury&columnUrl=mingche";
        }

        throw new InvalidParameterException(
                "Do not support this second domain name!");
    }

    protected boolean isDomainName(String secondDomainName) {
        if (secondDomainName.equalsIgnoreCase("www")
                || secondDomainName.equalsIgnoreCase("localhost")
                || secondDomainName.equalsIgnoreCase("fengsung")) {
            return true;
        }

        return false;
    }

    /**
     * 将URI转换成真正的请求URL
     *
     * @param URI
     * @return
     */
    protected String findRealPath(String secondDomainName, String URI) {
        for (URLMapping url : urlPatternList) {
            String domainName = url.getSecondDomain();
            boolean domainMatch = domainName == null || "".equals(domainName)
                    || secondDomainName.equalsIgnoreCase(domainName);
            Pattern pattern = Pattern.compile(url.getPattern());
            Matcher matcher = pattern.matcher(URI);

            if (matcher.find() && domainMatch) {
                String reqPara = url.getReqParameter();
                reqPara = reqPara.replace("{secondDomain}", secondDomainName);

                for (int i = 1; i <= matcher.groupCount(); i++) {
                    reqPara = reqPara.replace("$" + i + "", matcher.group(i));
                }

                logger.debug("pattern " + url.getPattern()
                        + " found for secondDomainName: " + secondDomainName
                        + " and URI: " + URI + " and result is: " + reqPara);

                return reqPara;
            }
        }

        logger.debug("No rule found for URI: " + URI);
        return URI;
    }

    // Just for UT
    void setUrlPatternList(List<URLMapping> urlPatternList) {
        this.urlPatternList = urlPatternList;
    }
}
